﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static DevExpress.XtraPrinting.Native.ExportOptionsPropertiesNames;
using static gts.mc;

namespace 运动控制卡Demo
{
    public partial class FrmMain : Form
    {
        //获取轴号
        private short Axis { get => Convert.ToInt16(cbAxis.Text); }
        //保存返回值
        private short rtn;
        bool[] flag = new bool[8];
        public FrmMain()
        {
            InitializeComponent();
            Console.WriteLine(flag);
            cbAxis.SelectedIndex = 0;   
        }
        #region 初始化操作
        //初始化
        private void btnInit_Click(object sender, EventArgs e)
        {
            //channel打开运动控制器的方式。默认值为：0。 0：正常打开运动控制器。 1：内部调试方式，用户不能使用。 
            // param当 channel = 1 时，该参数有效
            //打开运动卡
            rtn = gts.mc.GT_Open(0, 1);
            if (rtn != 0)
            {
                MessageBox.Show("未打开运动卡");
                return;
            }
            //控制卡复位
            rtn = gts.mc.GT_Reset();
            rtn = gts.mc.GT_LoadConfig("GTS800.cfg");
            //axis 起始轴号。正整数。 
            //count 读取的轴数，默认为 1。正整数。
            // rtn = gts.mc.GT_ClrSts(1, 8);
            //开始定时器
            timer1.Enabled = true;
            Console.WriteLine("rtn=" + rtn);
        }
        //清除状态
        private void btnClear_Click(object sender, EventArgs e)
        {
            //axis 起始轴号。正整数。 
            //count 读取的轴数，默认为 1。正整数。
            rtn = gts.mc.GT_ClrSts(1, 8);
            Console.WriteLine("rtn=" + rtn);
        }
        //伺服使能
        private void btnOpen_Click(object sender, EventArgs e)
        {
            //if (flag[Axis-1]==false)
            //{
            //    //axis 打开伺服使能的轴的编号。正整数。
            //    rtn = gts.mc.GT_AxisOn(Axis);
            //    if (rtn != 0)
            //    {
            //        MessageBox.Show("伺服开启失败");
            //        return;
            //    }
            //    btnOpen.Text = "开启伺服";
            //    flag[Axis - 1] = true;
            //}
            //else
            //{
            //    //axis 打开伺服使能的轴的编号。正整数。
            //    rtn = gts.mc.GT_AxisOff(Axis);
            //    if (rtn != 0)
            //    {
            //        MessageBox.Show("伺服关闭失败");
            //        return;
            //    }
            //    btnOpen.Text = "关闭伺服";
            //    flag[Axis - 1] = false;
            //}
            if (btnOpen.Text == "伺服状态关闭")
            {
                rtn = gts.mc.GT_AxisOff(Axis);
            }
            else
            {
                rtn = gts.mc.GT_AxisOn(Axis);
            }
            Console.WriteLine("rtn=" + rtn);
        }
        //位置清零
        private void btnZero_Click(object sender, EventArgs e)
        {
            //axis 需要位置清零的起始轴号，正整数。
            //count 需要位置清零的轴数
            rtn = gts.mc.GT_ZeroPos(1, 8);
            Console.WriteLine("rtn=" + rtn);
        }
        #endregion
        #region 选择轴号下拉改变事件
        private void cbAxis_SelectedIndexChanged(object sender, EventArgs e)
        {
            //读取轴状态
            //axis 起始轴号，正整数。
            //32 位轴状态字
            int pSts = 0;
            //读取控制器时钟，默认值为：NULL，即不用读取控制器时钟。 
            uint pClock = 0;
            gts.mc.GT_GetSts(Axis, out pSts, 1, out pClock);
            //驱动器报警
            if ((pSts & 0x2) != 0)
            {
                PQuDong.BackColor = Color.Red;
            }
            else
            {
                PQuDong.BackColor = Color.Lime;
            }

            // 负向限位
            if ((pSts & 0x40) != 0)
            {
                pFu.BackColor = Color.Red;
            }
            else
            {
                pFu.BackColor = Color.Lime;
            }
            // 正向限位
            if ((pSts & 0x20) != 0)
            {
                pZheng.BackColor = Color.Red;
            }
            else
            {
                pZheng.BackColor = Color.Lime;
            }
            // 伺服使能标志
            if ((pSts & 0x200) != 0)
            {
                btnOpen.Text = "伺服状态关闭";
                pShiNeng.BackColor = Color.Red;
            }
            else
            {
                btnOpen.Text = "伺服使能状态";
                pShiNeng.BackColor = Color.Lime;
            }

        }
        #endregion
        #region 点位运动
        private void btnTrap_Click(object sender, EventArgs e)
        {
            //profile 规划轴号，正整数。 
            rtn = gts.mc.GT_PrfTrap(Axis);
            Console.WriteLine("rtn=" + rtn);
        }

        int pos = 0;
        double vel = 0;
        private void btnStart_Click(object sender, EventArgs e)
        {
            //定义点位运动结构体变量
            gts.mc.TTrapPrm trapPrm;
            //获取当前轴之前的点位运动的信息
            gts.mc.GT_GetTrapPrm(Axis, out trapPrm);
            trapPrm.acc = 0.5;
            trapPrm.dec = 0.5;
            trapPrm.smoothTime = 1;
            //设置点位运动参数
            gts.mc.GT_SetTrapPrm(Axis, ref trapPrm);
            //累加规划位置
            pos += Convert.ToInt32(txtTrapPos.Text);
            //获取点位速度
            vel = Convert.ToDouble(txtTrapVel.Text);
            //设置点位运动的距离和速度
            gts.mc.GT_SetVel(Axis, vel);
            gts.mc.GT_SetPos(Axis, pos);
            //开始点位运动
            gts.mc.GT_Update(1 << (Axis - 1));
            Console.WriteLine("rtn=" + rtn);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            //step 脉冲输出通道号，正整数。
            rtn = gts.mc.GT_Stop(1, 0);
            //gts.mc.GT_Stop(1 << (Axis - 1),0);
            Console.WriteLine("rtn=" + rtn);
        }
        #endregion
        #region 电动运动
        private void btnJog_Click(object sender, EventArgs e)
        {//设置电动模式
            rtn = gts.mc.GT_PrfJog(Axis);
            Console.WriteLine("rtn=" + rtn);
            //获取电动参数
            gts.mc.TJogPrm jogPrm;
            gts.mc.GT_GetJogPrm(Axis, out jogPrm);
            jogPrm.acc = 0.1;
            jogPrm.dec = 0.1;
            //jogPrm.smooth = 0;
            //设置电动参数
            gts.mc.GT_SetJogPrm(Axis, ref jogPrm);

        }
        private void btnzheng_KeyDown(object sender, KeyEventArgs e)
        {
            //设置电动参数速度
            gts.mc.GT_SetVel(Axis, -Convert.ToDouble(txtJogVel.Text));
            //更新轴运动
            gts.mc.GT_Update(1 << (Axis - 1));
        }



        private void btnzheng_KeyUp(object sender, KeyEventArgs e)
        {
            gts.mc.GT_Stop(1 << (Axis - 1), 0);

        }
         
        private void btnfu_KeyDown(object sender, KeyEventArgs e)
        {
            //设置电动参数速度
            gts.mc.GT_SetVel(Axis, Convert.ToDouble(txtJogVel.Text));
            //更新轴运动
            gts.mc.GT_Update(1 << (Axis - 1));
        }

        private void btnfu_KeyUp(object sender, KeyEventArgs e)
        {
            gts.mc.GT_Stop(1 << (Axis - 1), 0);
        }

        #endregion

        #region 定时器事件
        double prfpos, prfvel, encpos, encvel;
        uint clk;
        private void timer1_Tick(object sender, EventArgs e)
        {
            cbAxis_SelectedIndexChanged(null, null);
            GetPosAndVel();
            GetDOstatus();
            GetDIstatus();
        }

        private void GetPosAndVel()
        {
            //读取规划位置和实际位置
            gts.mc.GT_GetPrfPos(Axis, out prfpos, 1, out clk);
            txtPrfpos.Text = prfpos.ToString();
            gts.mc.GT_GetEncPos(Axis, out encpos, 1, out clk);
            txtEncpos.Text = encpos.ToString();
            //读取规划速度和实际速度
            gts.mc.GT_GetPrfVel(Axis, out prfvel, 1, out clk);
            txtPrfvel.Text = prfvel.ToString();
            gts.mc.GT_GetEncVel(Axis, out encvel, 1, out clk);
            txtEncvel.Text = encvel.ToString();
        }
        #endregion
        #region 插补运动
        //建立坐标系
        private void btnCrd_Click(object sender, EventArgs e)
        {
            gts.mc.TCrdPrm crdPrm = new TCrdPrm();
            // 建立三维的坐标系
            crdPrm.dimension = 2;
            // 坐标系的最大合成速度是: 500 pulse/ms
            crdPrm.synVelMax = 500;
            // 坐标系的最大合成加速度是: 2 pulse/ms^2
            crdPrm.synAccMax = 2;
            // 坐标系的最小匀速时间为0
            crdPrm.evenTime = 0;
            // 规划器1对应到X轴                       
            crdPrm.profile1 = 1;
            // 规划器2对应到Y轴
            crdPrm.profile2 = 2;
            // 需要设置加工坐标系原点位置
            crdPrm.setOriginFlag = 1;
            // 加工坐标系原点位置在(0,0,0)，即与机床坐标系原点重合
            crdPrm.originPos1 = 0;
            crdPrm.originPos2 = 0;
            rtn = gts.mc.GT_SetCrdPrm(1, ref crdPrm);
            Console.WriteLine("rtn=" + rtn);
        }

        private void btnLine_Click(object sender, EventArgs e)
        {
            //即将把数据存入坐标系1的FIFO0中，所以要首先清除此缓存区中的数据
            rtn = gts.mc.GT_CrdClear(1, 0);
            // 向缓存区写入第一段插补数据
            rtn = gts.mc.GT_LnXY(
                    1,              // 该插补段的坐标系是坐标系1
                    0, 30000,      // 该插补段的终点坐标(200000, 0)
                    50,                // 该插补段的目标速度：100pulse/ms
                    0.2,                // 插补段的加速度：0.1pulse/ms^2
                    0,              // 终点速度为0
                    0);             // 向坐标系1的FIFO0缓存区传递该直线插补数据
            // 向缓存区写入第二段插补数据
            rtn = gts.mc.GT_LnXY(1, 20000, 0, 100, 0.1, 0, 0);
            // 缓存区延时指令
            rtn = gts.mc.GT_BufDelay(
                1,				// 坐标系是坐标系1
                500,				// 延时400ms
                0);				// 向坐标系1的FIFO0缓存区传递该延时
            // 向缓存区写入第三段插补数据
            rtn = gts.mc.GT_LnXY(1, 30000, 30000, 100, 0.1, 0, 0);
            int Pspace = 0;
            //查询坐标系1的FIFO0中的剩余空间
            rtn = gts.mc.GT_CrdSpace(1, out Pspace, 0);
            // 启动坐标系1的FIFO0的插补运动
            rtn = gts.mc.GT_CrdStart(1, 0);
            //等待完成
            short PRun = 0;
            int pSegment = 0;
            rtn = gts.mc.GT_CrdStatus(1, out PRun, out pSegment, 0);
            do
            {
                Console.WriteLine("正在插补运动中还剩：" + pSegment + "段");
                rtn = gts.mc.GT_CrdStatus(1, out PRun, out pSegment, 0);
            }
            while (PRun == 1);
            Console.WriteLine("rtn=" + rtn);
            Console.WriteLine("Pspace=" + Pspace);
        }

        private void btnArc_Click(object sender, EventArgs e)
        {
            //即将把数据存入坐标系1的FIFO0中，所以要首先清除此缓存区中的数据
            rtn = gts.mc.GT_CrdClear(1, 0);
            // 向缓存区写入第一段插补数据

            GT_ArcXYR(1, 0, 20000, 20000, 0, 50, 0.2, 0, 0);
            // 启动坐标系1的FIFO0的插补运动
            rtn = gts.mc.GT_CrdStart(1, 0);
        }

        private void btnCircle_Click(object sender, EventArgs e)
        {
            //即将把数据存入坐标系1的FIFO0中，所以要首先清除此缓存区中的数据
            rtn = gts.mc.GT_CrdClear(1, 0);
            // 向缓存区写入第一段插补数据

            GT_ArcXYC(1, 0, 0, 0, 20000, 0, 50, 0.2, 0, 0);
            // 启动坐标系1的FIFO0的插补运动
            rtn = gts.mc.GT_CrdStart(1, 0);
        }

        private void btnTriangle_Click(object sender, EventArgs e)
        {
            //即将把数据存入坐标系1的FIFO0中，所以要首先清除此缓存区中的数据
            rtn = gts.mc.GT_CrdClear(1, 0);
            rtn = gts.mc.GT_LnXY(
                1,              // 该插补段的坐标系是坐标系1
                0, 20000,      // 该插补段的终点坐标(200000, 0)
                50,                // 该插补段的目标速度：100pulse/ms
                0.2,                // 插补段的加速度：0.1pulse/ms^2
                0,              // 终点速度为0
                0);             // 向坐标系1的FIFO0缓存区传递该直线插补数据
                                // 向缓存区写入第二段插补数据
            rtn = gts.mc.GT_LnXY(1, 40000, 0, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 0, 0, 100, 0.1, 0, 0);
            // 启动坐标系1的FIFO0的插补运动
            rtn = gts.mc.GT_CrdStart(1, 0);
        }

        private void btnRectangle_Click(object sender, EventArgs e)
        {
            rtn = gts.mc.GT_CrdClear(1, 0);
            rtn = gts.mc.GT_LnXY(
               1,              // 该插补段的坐标系是坐标系1
               0, 20000,      // 该插补段的终点坐标(200000, 0)
               50,                // 该插补段的目标速度：100pulse/ms
               0.2,                // 插补段的加速度：0.1pulse/ms^2
               0,              // 终点速度为0
               0);             // 向坐标系1的FIFO0缓存区传递该直线插补数据
                               // 向缓存区写入第二段插补数据
            rtn = gts.mc.GT_LnXY(1, 20000, 20000, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 20000, 0, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 0, 0, 100, 0.1, 0, 0);
            // 启动坐标系1的FIFO0的插补运动
            rtn = gts.mc.GT_CrdStart(1, 0);
        }
        private void btnStar_Click(object sender, EventArgs e)
        {
            //即将把数据存入坐标系1的FIFO0中，所以要首先清除此缓存区中的数据
            rtn = gts.mc.GT_CrdClear(1, 0);


            rtn = gts.mc.GT_LnXY(1, 20000, 0, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 0, -30000, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 10000, 10000, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 20000, -30000, 100, 0.1, 0, 0);
            rtn = gts.mc.GT_LnXY(1, 0, 0, 100, 0.1, 0, 0);
            // 启动坐标系1的FIFO0的插补运动
            rtn = gts.mc.GT_CrdStart(1, 0);

        }

        #endregion
        #region DO和DI
        private void GetDOstatus()
        {
            int pValue = 0;
            rtn = GT_GetDo(12, out pValue);
            // 注意：DO通用输出配置里面取反了，所以判断也得反着判断
            if ((pValue&(1<<0))==0)
            {
                DO0.LampColor = new Color[] { Color.Green };
            }
            else
            {
                DO0.LampColor = new Color[] { Color.Red };
            }
            if ((pValue & (1 << 1)) == 0)
            {
                DO1.LampColor = new Color[] { Color.Green };
            }
            else
            {
                DO1.LampColor = new Color[] { Color.Red };
            }
            if ((pValue & (1 << 2)) == 0)
            {
                DO2.LampColor = new Color[] { Color.Green };
            }
            else
            {
                DO2.LampColor = new Color[] { Color.Red };
            }
            if ((pValue & (1 << 3)) == 0)
            {
                DO3.LampColor = new Color[] { Color.Green };
            }
            else
            {
                DO3.LampColor = new Color[] { Color.Red };
            }
            if ((pValue & (1 << 4)) == 0)
            {
                DO4.LampColor = new Color[] { Color.Green };
            }
            else
            {
                DO4.LampColor = new Color[] { Color.Red };
            }
        }
        private void GetDIstatus()
        {
            int pValue = 0;
            rtn = GT_GetDi(12, out pValue);
            if ((pValue & (1 << 0)) == 0)
            {
                DI0.LampColor = new Color[] { Color.Green };
            }
            else
            {
                DI0.LampColor = new Color[] { Color.Red };
            }

        }

        private void btnQGXJ_Click(object sender, EventArgs e)
        {
            GT_SetDoBit(12,1,0);
            GT_SetDoBit(12, 2, 1);
        }

        private void btnQGSS_Click(object sender, EventArgs e)
        {
            GT_SetDoBit(12, 1, 1);
            GT_SetDoBit(12, 2, 0);
        }

        

        private void btnZSSK_Click(object sender, EventArgs e)
        {
            GT_SetDoBit(12, 3, 0);
            GT_SetDoBit(12, 4, 1);
        }

        
        private void btnZSZJ_Click(object sender, EventArgs e)
        {
            GT_SetDoBit(12, 3, 1);
            GT_SetDoBit(12, 4, 0);
        }

        private void btnCSD_Click(object sender, EventArgs e)
        {
            int pValue = 0;
            rtn = GT_GetDo(12, out pValue);
            if ((pValue & (1 << 4)) == 0)
            {
                GT_SetDoBit(12, 5, 1);

            }
            else
            {
                GT_SetDoBit(12, 5, 0);
            }
        }

     
        #endregion
    }
}
